/**
 * Created by jinxs on 14-7-4.
 *依赖
 * ui.mask.js
 * ui.loading.js
 * ui.position.js
 * ui.panel.js
 */
(function ($) {
    /**
     * 缓存名称
     * @type {string}
     * @private
     */
    var _cacheName = 'uiGrid';
    /**loadData
    * @class 表单
    * @requires {@link panel}
    * @constructor uiGrid
    * @summary 构造函数
    * @param [options] {Object|String} 组件配置参数|要调用的组件方法名
    * @param [param] {Object} 表示要调用的组件方法的参数
    * @example
    * // 构件组件
    * $('#selectAge').uiGrid({direction: 'left'});
    * // 调用组件方法options
    * $('#selectAge').uiGrid("options");
    */
    $.fn.uiGrid = function (options, param) {
        if (typeof options == 'string') {
            return $.fn.uiGrid.methods[options](this, param);
        }
        return this.each(function(){
            var me = $(this);
            var cache = me.data(_cacheName);

            options = options || {};
            if (cache) {
                $.extend(cache.options, options);
            } else {
                me.data(_cacheName, {
                    options: $.extend({}, $.fn.uiGrid.defaults, me.parseUIConfig(), options)
                });
            }
            _init(me);
        });
    };
    /**
    * 方法
    * @lends uiGrid.prototype
    */
    $.fn.uiGrid.methods = {
        /**
          * @summary获取所有配置
         * @name uiGrid#options
         * @function
         * @param target {jQuery}
         * @returns {*|Function|HTMLOptionsCollection|options|options}
         */
        options: function (target) {
            return $.data(target[0], _cacheName).options;
        },
        /**
        * @summary加载数据
        * @name uiGrid#loadData
        * @function
        * @param target {jQuery}
        * @param opts {String}
        * @returns {Array}
        */
        loadData: function (target, opts) {
            var options = $.data(target[0], _cacheName).options;
            options = $.extend({}, options, opts);
            $.data(target[0], _cacheName, {options: options});
            var palContent = target.uiPanel('content');
            var grid_data = palContent.children('.grid_data');
            _renderGridBody(target, palContent, grid_data);
        }
    };
    /**
    * 默认配置
    * @lends uiGrid.prototype
    */
    $.fn.uiGrid.defaults = {
        /**
        * @type Boolean
        * @default false
        * @summary 指示组件是否自动适应
        */
        autoFit: false,
        /**
        * @type Boolean
        * @default false
        * @summary 指示表格列宽是否适应
        */
        colFit: false,
        /**
        * @type Boolean
        * @default false
        * @summary 指示表格标题是否固定
        */
        gridTitleFix: false,
        /**
        * @type Boolean
        * @default true
        * @summary 指示组件是否显示边框
        */
        border: true,
        /**
        * @type String
        * @default ""
        * @summary 指示组件图标
        */
        icon: '',
        /**
        * @type String
        * @default ""
        * @summary 指示组件标题
        */
        title: '',
        /**
        * @type Number
        * @default 400
        * @summary 指示组件宽度
        */
        width: 400,
        /**
        * @type Number
        * @default 300
        * @summary 指示组件高度
        */
        height: 300,
        /**
        * @type Boolean
        * @default true
        * @summary 指示组件是否显示标题栏
        */
        showHeader: true,
        /**
        * @type String
        * @default ""
        * @summary 为组件加载的提示信息
        */
        loadMsg: '',
        /**
        * @type String
        * @default null
        * @summary 为组件加载数据
        */
        localData: null,
        /**
        * @type String
        * @default id
        * @summary 指示组件信息主键的字段名
        */
        idField: 'id',
        /**
        * 可选值有get, post
        * @type String
        * @default "post"
        * @summary 向指定的url请求数据时使用的方法
        */
        method: 'get',
        /**
        * @type String
        * @default ""
        * @summary 指定远程数据加载的url
        */
        url: '',
        tpl_head: '',
        tpl_body: '',
        /**
        * @type Object
        * @default {}
        * @summary 指示组件的请求参数
        */
        queryParams: {},
        /**
        * @type Number
        * @default 1
        * @summary 指示组件是的起始页
        */
        pageIndex: 1,
        /**
        * @type Number
        * @default 20
        * @summary 指示组件的页面大小
        */
        pageSize: 20,
        /**
        * @type Array
        * @default [20, 40, 50, 100, 200]
        * @summary 指示组件的页面大小选择项
        */
        pageList: [20, 40, 50, 100, 200]
    };
//////--------------------------------内部方法------------------------------
    /**
     * 初始化
     * @param target 目标对象
     */
    var _init = function (target) {
        var options = target.data( _cacheName).options;
        var content = target.children().detach();
        var grid_data = content.filter('.grid_data');
        var gridBody = grid_data.children('.ui_grid_data');
        var palContent;

        target.uiPanel({
            autoFit: options.autoFit,
            icon: options.icon,
            title: options.title,
            width: options.width,
            height: options.height,
            border: options.border,
            minWidth: 300,
            minHeight: 200,
            showHeader: options.showHeader,
            showBtnBar: false
        });
        gridBody.find('li').each(function(i){
            $(this).addClass('cell col_' + i);
        });
        options._tplBodyFn = template.compile(gridBody.html());
        gridBody.empty();
        palContent = target.uiPanel('content').append(content);

        $.uiLoading.add({
            container: palContent
        });

        _renderToolbar(palContent);
        _renderPagination(target, palContent, grid_data);
        _renderGridStyle(target, grid_data);
        _gridFit(target, grid_data);
        _renderGridBody(target, palContent, grid_data);
        target.bind('_resize', function () {
            _gridFit(target, grid_data);
            _renderView(target, grid_data);
        });
        return target;
    };
    /**
     * 渲染grid的标题
     * @param target
     * @param grid_data
     * @private
     */
    var _renderGridStyle = function (target, grid_data) {
        var options = target.data(_cacheName).options;
        var gridHeader = grid_data.find('.ui_grid_head');
        var gridBody = grid_data.find('.ui_grid_data');

        gridBody.unbind('scroll').bind('scroll', (function (scrollTop, gvHead) {
            return function(){
                var me = $(this);
                //防止垂直滚动时计算
                if (scrollTop != me.scrollTop()) {
                    scrollTop = me.scrollTop();
                    return;
                }
                gvHead.scrollLeft(me.scrollLeft());
            }
        })(gridBody.scrollTop(), gridHeader));
    };
    var _renderGridBody = function (target, palContent, grid_data) {
        var options = target.data(_cacheName).options;

        if (options.showLoading) {
            $.uiLoading.show({
                container: palContent
            });
        }
        if (options.localData) {
            _getData(target, palContent, grid_data, options.localData);
        } else {
            if (options.url != '') {
                var pagination = palContent.find('.grid_pagination');
                var ajaxData = options.queryParams;
                if (pagination.length > 0) {
                    ajaxData = $.extend({}, options.queryParams, {pageIndex: options.pageIndex, pageSize: options.pageSize});
                }
                $.ajax({
                    type: options.method,
                    url: options.url,
                    cache: false,
                    data: ajaxData,
                    dataType: "json",
                    success: function (data) {
                        _getData(target, palContent, grid_data, data);
                    },
                    fail: function () {
                        alert('加载远程数据' + options.url + '失败！');
                    }
                });
            }
        }
    }
    var _getData = function (target, palContent, grid_data, data) {
        var options = target.data(_cacheName).options;
        var gridBody = grid_data.find('div.ui_grid_data');
        var pagination = palContent.find('.grid_pagination');
        if (pagination.length > 0) {
            pagination.uiPagination('refresh', {total: data.total});
        }
        gridBody.html(options._tplBodyFn(data));
        _renderView(target, grid_data);
        _renderSelection(target, gridBody);
        if (options.showLoading) {
            $.uiLoading.hide({container: palContent});
        }
    };
    var _gridFit = function (target, grid_data) {
        grid_data.autoFit(true, false);
        grid_data.find('div.ui_grid_data').autoFit(true, false);
    }
    var _renderView = function (target, grid_data) {
        var targetId = target.attr('id');
        var options = target.data(_cacheName).options;
        var gridHeader = grid_data.children('div.ui_grid_head');
        var gridBody = grid_data.children('div.ui_grid_data');
        var headUl = gridHeader.children();
        var bodyUl = gridBody.children();
        if (bodyUl.length > 0) {
            var headLis = headUl.children();
            var bodyLis = bodyUl.eq(0).children();
            var tableWidth = 0;
            var staticWidth = 0;
            var fixedWidth = bodyLis.outerWidth()-bodyLis.width();
            var isFirst = !headLis.eq(0).hasClass('cell');
            var fitCols = [];
            var gridWidth = grid_data.width() - 20;

            bodyLis.each(function (index, value) {
                var me = $(this);
                var li = headLis.eq(index);
                var maxWidth = li.width();

                if(isFirst){
                    li.addClass('cell col_' + index);
                    if(!li[0].style.width){
                        maxWidth = Math.max(maxWidth, me.width());
                        fitCols[fitCols.length] = {index:index,width:maxWidth};
                    }
                    else{
                        staticWidth += maxWidth + fixedWidth;
                        li.css('width','');
                        $.globalCSS('#'+targetId+' .col_'+index,'width:'+maxWidth+'px');
                    }
                }
                tableWidth += maxWidth + fixedWidth;
            });
            if(isFirst){
                if (options.colFit) {
                    var ext = gridWidth - staticWidth;
                    var pct = ext / (tableWidth - staticWidth);
                    for(var i=0;i<fitCols.length;i++){
                        var w = Math.floor((fitCols[i].width + fixedWidth) * pct);
                        ext -= w;
                        w -= fixedWidth;
                        if(i==fitCols.length-1){
                            w += ext;
                        }
                        $.globalCSS('#'+targetId+' .col_'+fitCols[i].index,'width:'+w+'px;');
                    }
                    tableWidth = gridWidth;
                }
                bodyUl.width(tableWidth);
                headUl.width(tableWidth);
            }
            else{
                bodyUl.width(headUl.width());
            }
        }
    }
    var _renderSelection = function (target, gridBody) {
        var cks = gridBody.find(':checkbox.grid_selector'),
            fn = function(e){
                var ck = $(this),
                    tr = ck,
                    flag = !ck.is(':checkbox'),
                    ckAll = tr.closest('div.grid_data').children('.ui_grid_head').find(':checkbox.grid_selector');
                if(!flag || e.ctrlKey){
                    var cked = false;
                    if(!flag){
                        tr = ck.closest('ul');
                    }
                    else{
                        ck = tr.find(':checkbox.grid_selector');
                    }
                    cked = tr.hasClass('selected');
                    tr.toggleClass('selected',!cked);
                    ck[0].checked = !cked;
                }
                else{
                    ck = tr.find(':checkbox.grid_selector');
                    tr.siblings('.selected').removeClass('selected');
                    tr.parent().find(':checked.grid_selector').each(function(){this.checked = false;});
                    ck[0].checked = true;
                    tr.addClass('selected');
                }
                ckAll.each(function(){
                    var cked = tr.hasClass('selected');
                    if(cked){
                        tr.siblings().each(function(){
                            if(!$(this).hasClass('selected')){
                                cked = false;
                                return false;
                            }
                        });
                    }
                    this.checked = cked;
                    tr = cked = null;
                });
                if(flag){
                    return false;
                }
            };
        if(cks.length > 0){
            cks.change(fn).mousedown(function(){return false;});
            cks.closest('ul').mousedown(fn);
        }
        target.find('.ui_grid_head :checkbox.grid_selector').change(function(){
            var me = $(this),
                cked = this.checked,
                trs = me.closest('div.grid_data').children('.ui_grid_data').children();
            trs.each(function(){
                $(this).toggleClass('selected', cked).find(':checkbox.grid_selector').each(function(){
                    this.checked = cked;
                });
            });
            cked = null;
        });
    }
    var _renderToolbar = function (palContent) {
        var toolbar = palContent.find('.grid_toolbar');
        if (toolbar.length > 0) {
            toolbar.uiButtonBar({backgroundColor: '#ececec', direction: 'left'});
            toolbar.css('marginLeft', -1);
        }
    }
    var _renderPagination = function (target, palContent, grid_data) {
        var pagination = palContent.find('.grid_pagination');
        if (pagination.length) {
            var options = $.data(target[0], _cacheName).options;
            pagination.uiPagination({
                pageIndex: options.pageIndex,
                pageSize: options.pageSize,
                pageList: options.pageList,
                onSelectPage: function (pageIndex, pageSize) {
                    options.pageIndex = pageIndex;
                    options.pageSize = pageSize;
                    _renderGridBody(target, palContent, grid_data);
                },
                onChangePageSize: function (pageSize) {
                    options.pageSize = pageSize;
                    _renderGridBody(target, palContent, grid_data);
                }
            });
        }
    }
})(jQuery);

